package jp.ac.u_tokyo.dch.util;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.lang.xwork.StringUtils;

public class HttpConnectUtil {


	/** エンコード(UTF-8) */
    private static final String ENC_UTF8 = "UTF-8";

    /** Retry Handler */
    private static final DefaultHttpMethodRetryHandler RETRY_HANDLER = new DefaultHttpMethodRetryHandler(3, false);

    private static DchLogger logger = DchLogger.getLogger(HttpConnectUtil.class);

    public static String httpRequest(String url, Map<String, String> params) {

    	GetMethod method = getGetMethod(url, params);

    	return request(method);
    }

    /**
     * リクエストを送信します。
     *
     * Http関連の例外処理も行います。
     * Httpコネクションのクローズ処理も行います。
     *
     * @param method 送信するHttpMethod
     */
    private static String request(HttpMethod method) {

    	String result = null;
        try {

            // リクエスト
            HttpClient client = new HttpClient();
            int statusCode = client.executeMethod(method);

            // -----------------------------------------
            // 結果を確認
            // -----------------------------------------
            // ステータスコード
            logger.info("statusCode = " + statusCode);

            // ヘッダー
            Header[] headers = method.getResponseHeaders();
            for (int i = 0; i < headers.length; i++) {
            	logger.info("headers[" + i + "] = " + headers[i]);
            }

            // ボディ
            result = method.getResponseBodyAsString();
            // フッター
            Header[] footers = method.getResponseFooters();
            for (int i = 0; i < footers.length; i++) {
            	logger.info("footers[" + i + "] = " + footers[i]);
            }

        } catch (HttpException he) {
        	logger.error(he);
        } catch (IOException ioe) {
        	logger.error(ioe);
        } finally {
            method.releaseConnection();
        }

        return result;
    }

    /**
     * GetMethodを取得します。
     *
     * @return GetMethod
     */
    private static GetMethod getGetMethod(String url, Map<String, String> param) {

        List<String> paramList = new ArrayList<String>();

        for (Iterator<Map.Entry<String, String>> it = param.entrySet().iterator(); it.hasNext();) {

        	Map.Entry<String, String> entry = it.next();

        	if (StringUtils.isNotEmpty(entry.getValue())) {
        		paramList.add(entry.getKey() + "=" + encode(entry.getValue()));
        	}

        }

        url += "?" + StringUtils.join(paramList, "&");
        GetMethod method = new GetMethod(url);
        method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, RETRY_HANDLER);
        return method;
    }

	 /**
     * URLエンコードします。
     *
     * @param value 値
     * @return エンコード値
     */
    private static String encode(String value) {
        try {
            return URLEncoder.encode(value, ENC_UTF8);
        } catch (UnsupportedEncodingException e) {
        	logger.error(e);
            throw new RuntimeException(e);
        }
    }
}
